#include <boost/python.hpp>
#include <GL/glut.h>
#include <iostream>

#include "globalsManager.h"
#include "pyParticleEngine.h"
#include "pyScriptManager.h"
#include "textureManager.h"
#include "mathFunctions.h"


pyParticle::pyParticle()
{
	x=0; y=0; life=5; this->needsInitializing = true;
}
pyParticle::pyParticle(std::string fileName, int x, int y, float velX, float velY)
{
    this->fileName = fileName;
	this->x = x;
	this->y = y;
	this->life = life;
	this->velX = velX;
	this->velY = velY;
	this->needsInitializing = true;
	this->textureFileName = "IMAGE NOT INITIALIZED!";
	this->rotation = 0;
	this->blendType = "";

	this->kill = false;
	GM()->particleTotal++;
}
bool pyParticle::initialize()
{
    if (needsInitializing)
    {
        needsInitializing = false;
        return true;
    }
    return false;
}
std::string pyParticle::getFileName(){ return this->fileName; }
void pyParticle::draw()
{
	glEnable(GL_BLEND);
	glDisable(GL_DEPTH_TEST);
	glColor4f(cR/255.0f,cG/255.0f,cB/255.0f,alpha/255.0f);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);
	if(blendType.compare("dark") == 0)
        glBlendFunc(GL_DST_COLOR,GL_ZERO);
	TM()->setTexture(textureFileName);
    glPushMatrix();
        glTranslated(x,y,0);
        glRotatef(rotation,0,0,1);
        glScaled(width,height, 0);
        int layers=1;
        if(blendType.compare("dark") == 0)
            layers=5;
        for(int x=0; x<layers; x++)
        {
            glBegin(GL_QUADS);
                glTexCoord2f(1.0f,1.0f); glVertex3f(.5f,-.5f,0.0f);
                glTexCoord2f(1.0f,0.0f); glVertex3f(-.5f,-.5f,0.0f);
                glTexCoord2f(0.0f,0.0f); glVertex3f(-.5f,.5f,0.0f);
                glTexCoord2f(0.0f,1.0f); glVertex3f(.5f,.5f,0.0f);
            glEnd();
        }
    glPopMatrix();
}
float pyParticle::getX(){ return x; }
void pyParticle::setX(float value){ x=value; }
float pyParticle::getY(){ return y; }
void pyParticle::setY(float value){ y=value; }

float pyParticle::getVelX(){ return velX; }
void pyParticle::setVelX(float value){ velX=value; }
float pyParticle::getVelY(){ return velY; }
void pyParticle::setVelY(float value){ velY=value; }

float pyParticle::getCR() { return cR; }
void pyParticle::setCR(float value) { cR = value; }
float pyParticle::getCG() { return cG; }
void pyParticle::setCG(float value) { cG = value; }
float pyParticle::getCB() { return cB; }
void pyParticle::setCB(float value) { cB = value; }
float pyParticle::getAlpha() { return alpha; }
void pyParticle::setAlpha(float value) { alpha = value; }

void pyParticle::setTextureFileName(std::string in) { textureFileName = in; }
std::string pyParticle::getTextureFileName() { return textureFileName; }

float pyParticle::getWidth() { return width; }
void pyParticle::setWidth(float value) { width = value; }
float pyParticle::getHeight() { return height; }
void pyParticle::setHeight(float value) { height = value; }

float pyParticle::getRotation() { return rotation; }
void pyParticle::setRotation(float value) { rotation = value; }

int pyParticle::getLife(){ return life; }
void pyParticle::setLife(int value){ life=value; }

std::string pyParticle::getBlendType(){ return blendType; }
void pyParticle::setBlendType(std::string value){ blendType=value; }

void pyParticle::lifeCheck(int index, pyEmitter* e)
{
	life--;
	if (life<=0)
	{
		//(*e).addToDeleteQeue(index);
		kill = true;
	}
}

pyEmitter::pyEmitter(){}

pyEmitter::pyEmitter(std::string fileName, float x, float y, boost::python::object *namespc)
{
	global = namespc;
	this->emitterFileName = fileName;
	this->x = x;
	this->y = y;
	this->scriptNotRunYet = true;
	this->mainParticleScript = "";
	this->timer = 0;
	this->float01 = 0;
}

pyParticle& pyEmitter::getParticle(int index)
{
	return *particleList[index];
}
int pyEmitter::getParticleTotal()
{
	return particleList.size();
}

void pyEmitter::update()
{

    try {
        (*global)["e"] = boost::python::ptr(this);
        if(timer<=0)
        {
						

            std::string emFileName=GM()->PATH+emitterFileName;
            exec((boost::python::str)(PM()->getScript(emitterFileName)),(*global),(*global)); //CAUSES ERROR ON WINDOWS

        }else{
            timer--;
        }
        if(this->scriptNotRunYet) //script generation!
        {
            this->scriptNotRunYet = false; //the script is run, so we now know all the particles that will be created. And the emitters script has been created from the .py files.
            //Time to generate the particle script.
            mainParticleScript += "for x in range (e.getParCount()):\n p=e.getParticle(x)\n";
            for(int x=0; x<fileNames.size(); x++)
            {
                std::string temp = PM()->getScript(fileNames[x]);

                mainParticleScript += " if(p.getFileName() == '" + fileNames[x] + "'):\n";
                addSpaces(&temp,2);
                mainParticleScript += temp + "\n";
            }
            mainParticleScript += " p.draw()\n p.lifeHandle(x,e)";
        }


        exec((boost::python::str)(mainParticleScript),(*global),(*global));
        particleCleanup();
    }catch(boost::python::error_already_set)
    {
        PyErr_Print();
    }

}
void pyEmitter::createParticle(std::string fileName, float x, float y, float velX, float velY)
{
    //check to see if its in the fileName list if not add it.
    if(this->scriptNotRunYet)
    {
        std::vector<std::string>::iterator it;
        bool itsIn = false;
        for(it = fileNames.begin(); it != fileNames.end(); it++)
        {
            if((*it) == fileName)
                itsIn = true;
        }
        if (itsIn == false)
            fileNames.push_back(fileName);
    }
	pyParticle* p = new pyParticle(fileName, x, y, velX, velY);
	p->setWidth(33); p->setHeight(33);
	p->setCR(0); p->setCG(0); p->setCB(0); p->setAlpha(255);
	particleList.push_back(p);
}
void pyEmitter::particleCleanup()
{
	int pSize = particleList.size();
	std::vector<pyParticle*>::iterator pEnd = particleList.end();
	//if(!deleteQeue.empty())
	//{
		//for(int z=deleteQeue.size()-1; z>=0; z--)
		for (std::vector<pyParticle*>::iterator it = particleList.begin(); it!=particleList.end(); ++it)
		{
			if((*it)->kill == true)
			{
				delete (*it);
				it = particleList.erase(it);
				//std::cout << "particle killed.";
			}
			//delete particleList[pSize-(pSize - deleteQeue[z])];
			//particleList.erase(pEnd-(pSize - deleteQeue[z]));
			//int x = *it;
			//pEnd = 
			//delete particleList[*it];
			//particleList.erase(*it);
			GM()->particleTotal--;
		}
		deleteQeue.clear();
	//}
}
void pyEmitter::addToDeleteQeue(int value)
{
	deleteQeue.push_back(value);
}

float pyEmitter::getX(){return x;}
void pyEmitter::setX(float value){x=value;}
float pyEmitter::getY(){return y;}
void pyEmitter::setY(float value){y=value;}

float pyEmitter::getFloat01(){ return float01; }
void pyEmitter::setFloat01(float value){this->float01=value;}

int pyEmitter::getTimer(){return timer;}
void pyEmitter::setTimer(int value){timer=value;}


struct pyEmitterSet{
	std::string fileName;
	std::vector<pyEmitter*> set;
};


struct emList
{
	std::string emitterFileName;
	std::vector<pyEmitter*> list;
};
